//Rect.cpp

#include "Rect.h"

Rect::Rect(const Point& point, int ver, int hor):Shape(point)
{
	m_ver = ver;
	m_hor = hor;
}

void Rect::set(int x, int y, int ver, int hor)
{
	m_point.set(x, y);
	m_ver = ver;
	m_hor = hor;
}

void Rect::set(const Point& point, int ver, int hor)
{
	m_point = point;
	m_ver = ver;
	m_hor = hor;
}

void Rect::draw(char ch, bool isFullFill) const
{
	//draw to the screen the rectangle frame
	for(int i=0; i<m_hor; i++)	//drawing first row of the frame
		m_point.draw(ch, i, 0);
	for (int i=1; i<m_ver-1; i++)	//drawing the middle rows of the frame
	{
		m_point.draw(ch, 0, i);
		m_point.draw(ch, m_hor-1, i);
	}
	for (int i=0; i<m_hor; i++)	//drawing last row of the frame
		m_point.draw(ch, i, m_ver-1);
	if (isFullFill)	//if the rectangle is with full fill
	{
		for (int i=1; i<m_ver-1; i++)	//drawing the middle rows of the fill
			for (int j=1; j<m_hor-1; j++)
				m_point.draw(' ', j, i);
	}
}

void Rect::drawToBuffer(char ch, bool isFullFill, bool isSplit, Screen& scr) const
{
	//draw to the screen the rectangle frame
	for(int i = 0; i < m_hor; i++)	//drawing first row of the frame
		m_point.drawToBuffer(ch, i, 0, scr, isSplit);
	for (int i=1; i<m_ver-1; i++)	//drawing the middle rows of the frame
	{
		m_point.drawToBuffer(ch, 0, i, scr, isSplit);
		m_point.drawToBuffer(ch, m_hor - 1, i, scr, isSplit);
	}
	for (int i=0; i<m_hor; i++)	//drawing last row of the frame
		m_point.drawToBuffer(ch, i , m_ver - 1, scr, isSplit);
	if (isFullFill)	//if the rectangle is with full fill
	{
		for (int i=1; i<m_ver-1; i++)	//drawing the middle rows of the fill
			for (int j=1; j<m_hor-1; j++)
				m_point.drawToBuffer(' ', j , i, scr, isSplit);
	}
}

bool Rect::isPointInside(const Point& point) const
{
	Point l_point = point;

	if (((l_point.getX() >= m_point.getX()) && (l_point.getX() <= (m_point.getX() + (m_hor - 1)))) &&
		((l_point.getY() >= m_point.getY()) && (l_point.getY() <= (m_point.getY() + (m_ver - 1)))))
		return true;
	else
		return false;
}

bool Rect::isInScreenBoarder() const
{
	int pointX = m_point.getX(); //x value of point
	int pointY = m_point.getY();	//y value of point

	if (pointX >= 0 && (pointX + m_hor) < SCR_HOR && pointY >= 0 && (m_point.getY() + m_ver) < SCR_VER)
		return true;
	else
		return false;
}

// Handles collision between rectangle and other shape
void Rect::handleCollisions(Shape* otherShape)
{
        if( typeid(*otherShape) == typeid(Rect) ) // if rectangle collides with other rectangle
        {
			CollisionsHandler::handleCollisions(this, (Rect*)otherShape);
				
        }
        if( typeid(*otherShape) == typeid(Circle) ) // if rectangle collides with circle
        {
            CollisionsHandler::handleCollisions(this, (Circle*)otherShape);
        }
}

void Rect::writeToFile(ofstream& outFile, bool isBinary) const
{
	int pointX = getXPoint();
	int pointY = getYPoint();
	int var = m_ver;
	int hor = m_hor;
	float shiftVer = m_shiftVer;
	float shiftHor = m_shiftHor;
	string typeShpe = typeid(Rect).name();

	if (isBinary)
	{
		outFile.write(reinterpret_cast <const char *> (&typeShpe), sizeof(string));
		outFile.write(reinterpret_cast <const char *> (&pointX), sizeof(int));
		outFile.write(reinterpret_cast <const char *> (&pointY), sizeof(int));
		outFile.write(reinterpret_cast <const char *> (&var), sizeof(int));
		outFile.write(reinterpret_cast <const char *> (&hor), sizeof(int));
		outFile.write(reinterpret_cast <const char *> (&shiftVer), sizeof(float));
		outFile.write(reinterpret_cast <const char *> (&shiftHor), sizeof(float));
	}
	else
	{
		outFile << typeShpe.c_str() << " "  << pointX << " " << pointY << " " << var << " " << hor << " " << shiftVer << " " << shiftHor << " ";
	}
}

void Rect::readFromFile(ifstream& inFile, bool isBinary)
{
	int pointX = getXPoint();
	int pointY = getYPoint();
	int var = m_ver;
	int hor = m_hor;
	float shiftVer = m_shiftVer;
	float shiftHor = m_shiftHor;

	if (isBinary)
	{
		inFile.read(reinterpret_cast <char *> (&pointX), sizeof(int));
		inFile.read(reinterpret_cast <char *> (&pointY), sizeof(int));
		inFile.read(reinterpret_cast <char *> (&var), sizeof(int));
		inFile.read(reinterpret_cast <char *> (&hor), sizeof(int));
		inFile.read(reinterpret_cast <char *> (&shiftVer), sizeof(float));
		inFile.read(reinterpret_cast <char *> (&shiftHor), sizeof(float));
	}
	else
		inFile >> pointX >> pointY >> var >> hor >> shiftVer >> shiftHor;
	set(pointX, pointY, var, hor);
	setShifts(shiftVer, shiftHor);
}